package commons.reflect.examples;

import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;

public class Formatter {
    private Map<TypeLiteral<?>, Function<?, String>> rules = new HashMap<TypeLiteral<?>, Function<?, String>>();

    /**
     * Add formatting rule to this formatter.
     * @param typeLiteral
     * @param formatter
     */
    public <T> void forType(TypeLiteral<T> typeLiteral, Function<T, String> formatter) {
        rules.put(typeLiteral, formatter);
    }
    
    public String formatFields(Object obj) throws IllegalAccessException {
        var builder = new StringBuilder();
        for (Field field : obj.getClass().getDeclaredFields()) {
            builder.append(field.getName());
            builder.append("=");
            field.setAccessible(true);
            var formatterForType = rules.get(TypeLiteral.of(field.getGenericType()));
            if (formatterForType != null) {
                Function<Object, String> formatter = (Function<Object, String>) formatterForType;
                builder.append(formatter.apply(field.get(obj)));
            } else {
                builder.append(field.get(obj).toString());
            }
            builder.append("\n");
        }
        return builder.toString();
    }
}
